using System;
using AltNetHispano.Vale.Tests.Example;
using NUnit.Framework;
using SharpTestsEx;

namespace AltNetHispano.Vale.Tests
{
	public class ValidatorTest
	{
		[Test]
		public void WhenValidatePersonWithDefaultValuesThenResturnsInvalidMessages()
		{
			IValidator validator = new Validator();
			validator.Register<Person>(p => validator.StringIsRequired("Name", p.Name));
			validator.Register<Person>(p => validator.StringIsRequired("Surname", p.Surname));
			validator.Register<Person>(p => validator.DateIsInThePast("Birthday", p.Birthday));

			var person = new Person { Name = null, Surname = null, Birthday = DateTime.Today };
			var invalidMessages = validator.GetInvalidMessages(person);
			invalidMessages.Should().Contain("Name is required.");
			invalidMessages.Should().Contain("Surname is required.");
			invalidMessages.Should().Contain("Birthday should be in the past.");
		}

		[Test]
		public void WhenValidateAddressInvalidWithDefaultValuesThenReturnInvalidMessagges()
		{
			IValidator validator = new Validator();
			validator.Register<Address>(p => validator.StringIsRequired("City", p.City));

			var address = new Address { City = null };
			var invalidMessages = validator.GetInvalidMessages(address);
			invalidMessages.Should().Contain("City is required.");
		}

		[Test]
		public void WhenEntityIsNullThenThrows()
		{
			IValidator validator = new Validator();
			validator.Executing(v=> v.GetInvalidMessages(null)).Throws<ArgumentNullException>();
		}

		[Test]
		public void WhenStringThen()
		{
			IValidator validator = new Validator();

			validator.GetInvalidMessages("Hola mundo").Should().Be.Empty();
		}

		[Test]
		public void WhenRegisterAValidationThenAddValidationToValidators()
		{
			Validator validator = new Validator();
			validator.Register<Person>(p => validator.StringIsRequired("Name", p.Name));
			validator.Register<Person>(p => validator.StringIsRequired("Surname", p.Surname));

			validator.ValidatorsHolder.Keys.Should().Contain(typeof (Person));
			validator.ValidatorsHolder[typeof (Person)].Should().Have.Count.EqualTo(2);
		}

		[Test]
		public void WhenValidatePersonWithDefaultValuesThenIsValidResturnFalse()
		{
			IValidator validator = new Validator();
			validator.Register<Person>(p => validator.StringIsRequired("Name", p.Name));
			validator.Register<Person>(p => validator.StringIsRequired("Surname", p.Surname));
			validator.Register<Person>(p => validator.DateIsInThePast("Birthday", p.Birthday));

			var person = new Person { Name = null, Surname = null, Birthday = DateTime.Today };
			validator.IsValid(person).Should().Be.False();
		}

		[Test]
		public void WhenValidateValidPersonThenIsValidResturnTrue()
		{
			IValidator validator = new Validator();
			validator.Register<Person>(p => validator.StringIsRequired("Name", p.Name));
			validator.Register<Person>(p => validator.StringIsRequired("Surname", p.Surname));
			validator.Register<Person>(p => validator.DateIsInThePast("Birthday", p.Birthday));

			var person = new Person { Name = "0123456789", Surname = "0123456789", Birthday = DateTime.Today.AddDays(-10) };
			validator.IsValid(person).Should().Be.True();
		}

		[Test]
		public void WhenValidateInvalidPersonThenShouldExecuteOnlyTheFirstInvalidCheck()
		{
			bool nameChecked = false;
			bool surnameChecked = false;
			bool birthdayChecked = false;
			IValidator validator = new Validator();
			validator.Register<Person>(p =>
			                           	{
			                           		nameChecked = true;
			                           		return validator.StringIsRequired("Name", p.Name);
			                           	});
			validator.Register<Person>(p =>
			                           	{
			                           		surnameChecked = true;
			                           		return validator.StringIsRequired("Surname", p.Surname);
			                           	});
			validator.Register<Person>(p =>
			                           	{
			                           		birthdayChecked = true;
			                           		return validator.DateIsInThePast("Birthday", p.Birthday);
			                           	});

			var person = new Person { Name = null, Surname = null, Birthday = DateTime.Today };
			validator.IsValid(person);
			nameChecked.Should().Be.True();
			surnameChecked.Should().Be.False();
			birthdayChecked.Should().Be.False();
		}
	}
}